package com.tk.exam.service.impl;

import com.github.pagehelper.Page;
import com.tk.exam.dao.TkExamPaperDao;
import com.tk.exam.dao.TkQuestionDao;
import com.tk.exam.dao.TkRPaperQuestionDao;
import com.tk.exam.domain.*;
import com.tk.exam.exception.ApiException;
import com.tk.exam.mapper.TkExamInfoMapper;
import com.tk.exam.mapper.TkExamPaperMapper;
import com.tk.exam.mapper.TkRPaperQuestionMapper;
import com.tk.exam.service.TkExamPaperManagerService;
import com.tk.exam.vo.paper.ExamPaperRequestVo;
import com.tk.exam.vo.paper.PaperVo;
import com.tk.exam.vo.paper.QuesVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class TkExamPaperManagerServiceImpl implements TkExamPaperManagerService {
    @Autowired
    private TkExamPaperDao tkExamPaperDao;
    @Autowired
    private TkRPaperQuestionDao tkRPaperQuestionDao;
    @Autowired
    private TkQuestionDao tkQuestionDao;
    @Autowired
    private TkExamInfoMapper tkExamInfoMapper;
    @Autowired
    private TkRPaperQuestionMapper tkRPaperQuestionMapper;
    @Autowired
    private TkExamPaperMapper tkExamPaperMapper;
    @Override
    @Transactional
    public TkExamPaper save(ExamPaperRequestVo examPaperRequestVo) {
        Date date = new Date();
        TkExamPaper examPaper;
        if(examPaperRequestVo.getId()!=null){
            log.info("更新试卷");
            //更新
            examPaper = tkExamPaperDao.findById(Integer.valueOf(examPaperRequestVo.getId()));
            if(Objects.isNull(examPaper)){
                throw ApiException.of("试卷不存在");
            }
            //清除试题与试卷的旧关系
            List<TkRPaperQuestion> tkRPaperQuestions = findTkRpaperQuesById(examPaper.getId().toString());
            if(CollectionUtils.isEmpty(tkRPaperQuestions)){
                throw ApiException.of("试卷内不存在试题，错误数据，试卷id"+examPaper.getId());
            }
            deleteTkRpaperQues(tkRPaperQuestions);
        }else{
            //新增试卷
            log.info("新增试卷");
            examPaper = new TkExamPaper();
            examPaper.setCreateTime(date);
        }
        return saveExamAndRelation(examPaper,examPaperRequestVo,date);
    }

    @Override
    public ExamPaperRequestVo findExamPaperInfoById(String id) {
        TkExamPaper examPaper = tkExamPaperDao.findById(Integer.valueOf(id));
        if(Objects.isNull(examPaper)){
            throw ApiException.of("试卷不存在");
        }
        ExamPaperRequestVo vo = new ExamPaperRequestVo();
        vo.setId(examPaper.getId().toString());
        vo.setPaperName(examPaper.getPaperName());

        List<TkRPaperQuestion> tkRPaperQuestions = findTkRpaperQuesById(id);
//        1:单选题,2:判断题,3:填空题,4:简答题,5:4C题
        List<TkRPaperQuestion> dxQuesList = tkRPaperQuestions.stream().filter(tkRPaperQuestion ->"1".equals(tkRPaperQuestion.getQuestionType().toString())).collect(Collectors.toList());
        List<TkRPaperQuestion> pdQuesList = tkRPaperQuestions.stream().filter(tkRPaperQuestion ->"2".equals(tkRPaperQuestion.getQuestionType().toString())).collect(Collectors.toList());
        List<TkRPaperQuestion> tkQuesList = tkRPaperQuestions.stream().filter(tkRPaperQuestion ->"3".equals(tkRPaperQuestion.getQuestionType().toString())).collect(Collectors.toList());
        List<TkRPaperQuestion> jsQuesList = tkRPaperQuestions.stream().filter(tkRPaperQuestion ->"4".equals(tkRPaperQuestion.getQuestionType().toString())).collect(Collectors.toList());
        List<TkRPaperQuestion> scQuesList = tkRPaperQuestions.stream().filter(tkRPaperQuestion ->"5".equals(tkRPaperQuestion.getQuestionType().toString())).collect(Collectors.toList());
        //避免建立过多数据库连接，一次查出试卷标题结果
        Map<String,String> map = findQuesInfoByIds(tkRPaperQuestions);
        List<QuesVo> dxQues = packQuesVoFromList(dxQuesList,map);
        List<QuesVo> pdQues = packQuesVoFromList(pdQuesList,map);
        List<QuesVo> tkQues = packQuesVoFromList(tkQuesList,map);
        List<QuesVo> jsQues = packQuesVoFromList(jsQuesList,map);
        List<QuesVo> scQues = packQuesVoFromList(scQuesList,map);

        PaperVo dxPaperVo = packPaperVo(dxQues,"1");
        PaperVo pdPaperVo = packPaperVo(pdQues,"2");
        PaperVo tkPaperVo = packPaperVo(tkQues,"3");
        PaperVo jsPaperVo = packPaperVo(jsQues,"4");
        PaperVo scPaperVo = packPaperVo(scQues,"5");

        vo.setDxQues(dxPaperVo);
        vo.setScQues(scPaperVo);
        vo.setJsQues(jsPaperVo);
        vo.setTkQues(tkPaperVo);
        vo.setPdQues(pdPaperVo);

        return vo;
    }

    @Override
    @Transactional
    public int deleteExamPapers(List<Integer> ids) {
        if(checkExamPapers(ids)){
            throw ApiException.of("试卷已被考试引用，不能删除");
        }
        //删除试卷及试题与试卷的关系
        TkRPaperQuestionExample rPaperQuestionExample = new TkRPaperQuestionExample();
        rPaperQuestionExample.or().andExamPaperIdIn(ids);

        int i = tkRPaperQuestionMapper.deleteByExample(rPaperQuestionExample);

        TkExamPaperExample paperExample = new TkExamPaperExample();
        paperExample.or().andIdIn(ids);

        int j = tkExamPaperMapper.deleteByExample(paperExample);
        return j;
    }

    @Override
    public boolean checkExamPapers(List<Integer> ids) {

        TkExamInfoExample examInfoExample = new TkExamInfoExample();
        examInfoExample.or().andExamPaperIdIn(ids);
        List<TkExamInfo> tkExamInfos = tkExamInfoMapper.selectByExample(examInfoExample);
        if(!CollectionUtils.isEmpty(tkExamInfos)){
            return true;
        }
        return false;
    }

    public List<QuesVo> packQuesVoFromList(List<TkRPaperQuestion> list, Map<String,String> map){
        List<QuesVo> childDxQues = new ArrayList<QuesVo>();
        list.forEach(rPaperQuestion -> {
            QuesVo quesVo = new QuesVo();
            quesVo.setId(rPaperQuestion.getQuestionId().toString());
            quesVo.setQuesName(map.get(rPaperQuestion.getQuestionId().toString()));
            quesVo.setQuesOrder(rPaperQuestion.getSortIndex().toString());
            quesVo.setScore(rPaperQuestion.getQuestionSocre());
            childDxQues.add(quesVo);
        });
        List<QuesVo> ques = childDxQues.stream().sorted(Comparator.comparing(QuesVo::getQuesOrder)).collect(Collectors.toList());
        return ques;
    }

    public PaperVo packPaperVo(List<QuesVo> ques,String type){
        if(CollectionUtils.isEmpty(ques)){
             return null;
        }
        PaperVo paperVo = new PaperVo();
        int num = ques.size();
        double score = ques.get(0).getScore();
        paperVo.setQues(ques);
        paperVo.setChoseNum(ques.size());
        paperVo.setQuesType(type);
        paperVo.setTotalScore(score*num);
        paperVo.setScore(score);
        return paperVo;
    }


    @Transactional
    public TkExamPaper saveExamAndRelation(TkExamPaper examPaper,ExamPaperRequestVo examPaperRequestVo,Date date){
        examPaper.setPaperName(examPaperRequestVo.getPaperName());
        //判断试题数量和传入参数是否一致
        Map map = checkQuesNum(examPaperRequestVo);
        if("false".equals(map.get("isRight"))){
            throw ApiException.of("题目数量与实际勾选不符或者每种题型总分有误或未选择任何题型的试题");
        }
        Integer totalNum = (Integer) map.get("totalNum");
        Double totalScore = (Double) map.get("totalScore");
        examPaper.setQuestionNum(totalNum);
        examPaper.setTotalScore(totalScore);
        examPaper.setUpdateTime(date);
        examPaper = tkExamPaperDao.save(examPaper);
        //新增试卷与试题关联关系
        List<TkRPaperQuestion> tkRPaperQuestions = saveRelation(examPaper.getId().toString(),examPaperRequestVo);
        if(CollectionUtils.isEmpty(tkRPaperQuestions)){
            throw ApiException.of("试题列表不能为空");
        }
        //校验试题是否存在
        if(!checkQues(tkRPaperQuestions)){
            throw ApiException.of("试题勾选重复或试题不存在");
        }
        try{
            tkRPaperQuestionDao.insertBatch(tkRPaperQuestions);
        }catch (DuplicateKeyException exception){
            throw ApiException.of("试题重复或者序号重复，请重新勾选");
        }
        return examPaper;
    }

    public Map<String,Object> checkQuesNum(ExamPaperRequestVo examPaperRequestVo){
        Map map = new HashMap();
        PaperVo dxPaper = examPaperRequestVo.getDxQues();
        PaperVo tkPaper = examPaperRequestVo.getTkQues();
        PaperVo jsPaper = examPaperRequestVo.getJsQues();
        PaperVo pdPaper = examPaperRequestVo.getPdQues();
        PaperVo scPaper = examPaperRequestVo.getScQues();
        map.put("isRight","true");
        //入参的各题型数量
        int dxNum = 0;
        int tkNum = 0;
        int jsNum = 0;
        int pdNum = 0;
        int scNum = 0;
        //未选择任何题型
        if(Objects.isNull(dxPaper) && Objects.isNull(tkPaper) && Objects.isNull(jsPaper) &&  Objects.isNull(pdPaper) && Objects.isNull(scPaper)){
            map.put("isRight","false");
        }
        //试题列表
        List dx = null;
        List tk = null;
        List js = null;
        List pd = null;
        List sc = null;

        double dxScore = 0;
        double tkScore = 0;
        double jsScore = 0;
        double pdScore = 0;
        double scScore = 0;
        if(!Objects.isNull(dxPaper)){
            dxNum = Integer.valueOf(dxPaper.getChoseNum());
            dx = dxPaper.getQues();
            dxScore = dxPaper.getTotalScore();
        }
        if(!Objects.isNull(tkPaper)){
            tkNum = Integer.valueOf(tkPaper.getChoseNum());
            tk = tkPaper.getQues();
            tkScore = tkPaper.getTotalScore();
        }
        if(!Objects.isNull(jsPaper)){
            jsNum = Integer.valueOf(jsPaper.getChoseNum());
            js = jsPaper.getQues();
            jsScore = jsPaper.getTotalScore();
        }
        if(!Objects.isNull(pdPaper)){
            pdNum = Integer.valueOf(pdPaper.getChoseNum());
            pd = pdPaper.getQues();
            pdScore = pdPaper.getTotalScore();
        }
        if(!Objects.isNull(scPaper)){
            scNum = Integer.valueOf(scPaper.getChoseNum());
            sc = scPaper.getQues();
            scScore = scPaper.getTotalScore();
        }

        log.info(dxNum+"aa"+tkNum+"bb"+pdNum+"cc"+jsNum+"dd"+scNum);

        //试题的数量
        int dxSize=0;
        int tkSize=0;
        int jsSize=0;
        int pdSize=0;
        int scSize=0;
        if(!CollectionUtils.isEmpty(dx)){
            dxSize=dx.size();
        }
        if(!CollectionUtils.isEmpty(tk)){
            tkSize=tk.size();
        }
        if(!CollectionUtils.isEmpty(js)){
            jsSize=js.size();
        }
        if(!CollectionUtils.isEmpty(pd)){
            pdSize=pd.size();
        }
        if(!CollectionUtils.isEmpty(sc)){
            scSize=sc.size();
        }

        if(dxNum!=dxSize ||tkNum!=tkSize ||jsNum!=jsSize ||pdNum!=pdSize ||scNum!=scSize){
            map.put("isRight","false");
        }
        if(!Objects.isNull(dxPaper) && dxScore!=(dxSize*dxPaper.getScore())
         || !Objects.isNull(pdPaper) && pdScore!=(pdSize*pdPaper.getScore())
         || !Objects.isNull(jsPaper) && jsScore!=(jsSize*jsPaper.getScore())
         || !Objects.isNull(tkPaper) && tkScore!=(tkSize*tkPaper.getScore())
         || !Objects.isNull(scPaper) && scScore!=(scSize*scPaper.getScore())){
            map.put("isRight","false");
        }
        Integer totalNum = dxNum+tkNum+jsNum+pdNum+scNum;
        Double totalScore =dxScore+pdScore+jsScore+tkScore+scScore;

        map.put("totalNum",totalNum);
        map.put("totalScore",totalScore);
        return map;
    }

    public boolean checkQues(List<TkRPaperQuestion> tkRPaperQuestions){
        List<Integer> ids = tkRPaperQuestions.stream().map(tkRPaperQues->tkRPaperQues.getQuestionId()).collect(Collectors.toList());
        List<TkQuestions> tkQuestions =  tkQuestionDao.findByIds(ids);
        log.info("已选择试题数量"+tkRPaperQuestions.size());
        log.info("已存在的试题数量"+tkQuestions.size());
        if(!CollectionUtils.isEmpty(tkQuestions) && tkRPaperQuestions.size()==tkQuestions.size()){
            return true;
        }
        return false;
    }
    public List<TkRPaperQuestion> saveRelation(String id,ExamPaperRequestVo vo){
        List<TkRPaperQuestion> tkRPaperQuestions = new ArrayList<TkRPaperQuestion>();
        //单选题
        if(!Objects.isNull(vo.getDxQues()) && !Objects.isNull(vo.getDxQues().getQues())){
            PaperVo paperVo = vo.getDxQues();
            Double score = Double.valueOf(paperVo.getScore());
            tkRPaperQuestions.addAll(packList(id,vo,score,paperVo));
        }
        //计算题
        if(!Objects.isNull(vo.getJsQues()) && !Objects.isNull(vo.getJsQues().getQues())){
            PaperVo paperVo = vo.getJsQues();
            Double score = Double.valueOf(paperVo.getScore());
            tkRPaperQuestions.addAll(packList(id,vo,score,paperVo));
        }
        //判断题
        if(!Objects.isNull(vo.getPdQues()) && !Objects.isNull(vo.getPdQues().getQues())){
            PaperVo paperVo = vo.getPdQues();
            Double score = Double.valueOf(paperVo.getScore());
            tkRPaperQuestions.addAll(packList(id,vo,score,paperVo));
        }
        //填空题
        if(!Objects.isNull(vo.getTkQues()) && !Objects.isNull(vo.getTkQues().getQues())){
            PaperVo paperVo = vo.getTkQues();
            Double score = Double.valueOf(paperVo.getScore());
            tkRPaperQuestions.addAll(packList(id,vo,score,paperVo));
        }
        //实操题
        if(!Objects.isNull(vo.getScQues()) && !Objects.isNull(vo.getScQues().getQues())){
            PaperVo paperVo = vo.getScQues();
            Double score = Double.valueOf(paperVo.getScore());
            tkRPaperQuestions.addAll(packList(id,vo,score,paperVo));
        }
        return tkRPaperQuestions;
    }

    public List<TkRPaperQuestion> packList(String id,ExamPaperRequestVo vo,Double score,PaperVo paperVo){
        List<TkRPaperQuestion> tkRPaperQuestions = new ArrayList<TkRPaperQuestion>();
        Date date = new Date();
        List<QuesVo> quesVoList = paperVo.getQues();
        quesVoList.forEach(quesVo -> {
            TkRPaperQuestion tkRPaperQuestion = new TkRPaperQuestion();
            tkRPaperQuestion.setExamPaperId(Integer.valueOf(id));
            tkRPaperQuestion.setQuestionId(Integer.valueOf(quesVo.getId()));
            tkRPaperQuestion.setQuestionSocre(score);
            tkRPaperQuestion.setSortIndex(Integer.valueOf(quesVo.getQuesOrder()));
            tkRPaperQuestion.setQuestionType(new Byte(paperVo.getQuesType()));
            tkRPaperQuestion.setCreateTime(date);
            tkRPaperQuestion.setUpdateTime(date);
            tkRPaperQuestions.add(tkRPaperQuestion);
        });

        return tkRPaperQuestions;
    }

    public List<TkRPaperQuestion> findTkRpaperQuesById(String examPaperId){
        return tkRPaperQuestionDao.findTkRpaperQuesById(Integer.valueOf(examPaperId));
    }
    @Transactional
    public void deleteTkRpaperQues(List<TkRPaperQuestion> tkRPaperQuestions){
        log.info("删除试卷内的试题"+tkRPaperQuestions);
        List<Integer> list = tkRPaperQuestions.stream().map(tkRPaperQuestion -> tkRPaperQuestion.getId()).collect(Collectors.toList());
        tkRPaperQuestionDao.deleteByIds(list);
    }

    public Map<String,String> findQuesInfoByIds(List<TkRPaperQuestion> tkRPaperQuestions){
        List<Integer> ids = tkRPaperQuestions.stream().map(tkRPaperQues->tkRPaperQues.getQuestionId()).collect(Collectors.toList());
        List<TkQuestions> tkQuestions =  tkQuestionDao.findByIds(ids);
        Map<String,String> map = new HashMap<>();
        tkQuestions.forEach(tkQues->{
            map.put(tkQues.getId().toString(),tkQues.getQuesTitle());
        });
        return map;
    }
}